package com.acmen.easyapi.parse;

import com.acmen.easyapi.factory.impl.DefaultClassAliasFactory;
import com.acmen.easyapi.model.ParamNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.*;

/**
 * @author acmen
 *
 * JAVA类解析器
 *
 */
public abstract class ParamParser {
    private static final Logger log = LoggerFactory.getLogger(ParamParser.class);

    /**
     * 存储参数节点的哈希映射表
     */
    protected Map<String, List<ParamNode>> paramNodeMap = new HashMap<>();


    /**
     *
     * @param type
     * @param typeMap
     * @return
     */
    public List<ParamNode> createParamNodes(Type type, Map<TypeVariable, Type> typeMap) {
                if (type instanceof WildcardType) {
            // 如果type是WildcardType类型，表示一种通配符类型表达式，比如List<? extends Number> numbers
            WildcardType wildcardType = (WildcardType) type;
            Type[] upperBounds = wildcardType.getUpperBounds();
            if (upperBounds.length > 0) {
                // 如果有上界，则返回上界对应的参数节点
                return createParamNodes(upperBounds[0], typeMap);
            } else {
                Type[] lowerBounds = wildcardType.getLowerBounds();
                // 如果没有上界，则返回下界对应的参数节点
                return createParamNodes(lowerBounds[0], typeMap);
            }
        } else if (type instanceof TypeVariable) {
            // 如果type是TypeVariable类型，表示各种类型变量的公共父接口,比如List<T> records，下面就是取出T对应的具体类型
            Type type_ = getTargetType(type, typeMap);
            if (type_ != null) {
                // 如果type_不为空，则返回type_对应的参数节点
                return createParamNodes(type_, typeMap);
            }
        } else if (type instanceof ParameterizedType) {
            // 如果type是ParameterizedType类型，表示一种参数化的类型，比如List list = new ArrayList<String>();
            ParameterizedType parameterizedType = (ParameterizedType) type;
            typeMap.putAll(getTypeMap(parameterizedType));
            // 例如List<String> ids,rawType为List，将parameterizedType中的类型映射添加到typeMap中
            Type rawType = parameterizedType.getRawType();
            Class  clazz = (Class) rawType;
            if (Collection.class.isAssignableFrom(clazz)) {
                // 如果rawType是Collection类或其子类，则返回参数节点
                Type paramType = parameterizedType.getActualTypeArguments()[0];
                return createParamNodes(paramType, typeMap);
            }  else {
                // 否则返回clazz对应的节点
                return createNodesForClass(clazz, typeMap);
            }
        } else if(type instanceof Class){
            // 如果type是Class类型
            Class clazz = (Class) type;
            if (clazz.isArray()) {
                // 如果是数组类型，则返回数组元素类型的参数节点
                return createParamNodes(clazz.getComponentType(), typeMap);
            } else {
                // 否则返回clazz对应的节点
                return createNodesForClass(clazz, typeMap);
            }
        }else{
            // 其他类型都没有处理，返回空列表，并记录日志
            log.warn("我开始懵逼了，我根本没有处理你这个类型，你等着!type="+type.getTypeName());
        }
        // 返回空的参数节点列表
        return new ArrayList<ParamNode>();

    }
    abstract protected List<ParamNode> createNodesForClass(Class clazz, Map<TypeVariable, Type> typeMap);

    /**
     * 获取数据类型
     *
     * @param typeMap
     * @return
     */
       /**
     * 获取数据类型的别名
     * @param type 数据类型
     * @param typeMap 类型变量映射表
     * @return 数据类型的别名
     */
    protected String getDataTypeAlias(Type type, Map<TypeVariable, Type> typeMap) {
               if (type instanceof WildcardType) {
            // 如果类型是通配符类型
            WildcardType wildcardType = (WildcardType) type;
            // 将类型转换为通配符类型
            Type[] upperBounds = wildcardType.getUpperBounds();
            // 获取通配符类型的一元上界
            if (upperBounds.length > 0) {
                // 如果有一元上界
                return getDataTypeAlias(upperBounds[0], typeMap);
                // 返回一元上界的类型数据别名
            } else {
                // 如果没有一元上界
                Type[] lowerBounds = wildcardType.getLowerBounds();
                // 获取通配符类型的一元下界
                return getDataTypeAlias(lowerBounds[0], typeMap);
                // 返回一元下界的类型数据别名
            }
        } else if (type instanceof ParameterizedType) {
            // 如果类型是参数化类型
            ParameterizedType parameterizedType = (ParameterizedType) type;
            // 将类型转换为参数化类型
            Class rawType = (Class) parameterizedType.getRawType();
            // 获取参数化的原始类型
            if(Collection.class.isAssignableFrom(rawType)){
                // 如果原始类型是Collection的子类
                Type[] params = parameterizedType.getActualTypeArguments();
                // 获取参数化类型的参数
                if(params.length>0){
                    // 如果有参数
                    return getDataTypeAlias(params[0],typeMap)+"[]";
                    // 返回参数类型的类型数据别名，并在末尾添加"[]"表示数组
                }else{
                    // 如果没有参数
                    return "Object[]";
                    // 返回"Object[]"
                }
            }else{
                // 如果原始类型不是Collection的子类
                return DefaultClassAliasFactory.getAlias(rawType);
                // 返回原始类型的类型数据别名
            }
        } else if (type instanceof TypeVariable) {
            // 如果类型是类型变量
            Type type_ = getTargetType(type, typeMap);
            // 获取类型变量的目标类型
            if (type_ != null) {
                // 如果目标类型存在
                return getDataTypeAlias(type_, typeMap);
                // 返回目标类型的类型数据别名
            } else {
                // 如果目标类型不存在
                return DefaultClassAliasFactory.getAlias(type);
                // 返回类型的默认类型数据别名
            }
        } else if (type instanceof Class) {
            // 如果类型是类
            Class clazz = (Class) type;
            // 将类型转换为类
            if (clazz.isEnum()) {
                // 如果类是枚举类型
                return DefaultClassAliasFactory.getAlias("enum");
                // 返回"enum"的默认类型数据别名
            } else if(clazz.isArray()){
                // 如果类是数组类型
                return getDataTypeAlias(clazz.getComponentType(),typeMap)+"[]";
                // 返回数组元素类型的类型数据别名，并在末尾添加"[]"表示数组
            }else{
                // 如果类不是枚举类型也不是数组类型
                return DefaultClassAliasFactory.getAlias(clazz);
                // 返回类的默认类型数据别名
            }
        } else {
            // 如果类型不是上述任何一种类型
            return DefaultClassAliasFactory.getAlias(type);
            // 返回类型的默认类型数据别名
        }

    }



    /**
     * 获取模板参数对应的类型
     *
     * @param type
     * @param typeMap
     * @return
     */
    protected Type getTargetType(Type type, Map<TypeVariable, Type> typeMap) {
               Type type_ = typeMap.get(type); // 根据指定的类型获取相应的类型
        if (type_ == null && type instanceof TypeVariable) { // 如果类型为空且type是TypeVariable的实例
            TypeVariable typeVariable = (TypeVariable) type; // 将type转换为TypeVariable类型
            for (Map.Entry<TypeVariable, Type> entry : typeMap.entrySet()) { // 遍历typeMap的entrySet
                TypeVariable typeVar = entry.getKey(); // 获取当前遍历的entry的key，赋值给typeVar
                if (typeVar.getName().equals(typeVariable.getName())) { // 如果typeVar的名字与typeVariable的名字相等
                    Class declaration1 = (Class) typeVar.getGenericDeclaration(); // 获取typeVar的GenericDeclaration，并将其转换为Class类型
                    Class declaration2 = (Class) typeVariable.getGenericDeclaration(); // 获取typeVariable的GenericDeclaration，并将其转换为Class类型
                    if (declaration1.isAssignableFrom(declaration2) || declaration2.isAssignableFrom(declaration1)) { // 如果declaration1能够转换为declaration2或者declaration2能够转换为declaration1
                        type_ = entry.getValue(); // 将当前遍历的entry的value赋值给type_
                    }
                }
            }
        }
        return type_; // 返回类型type_

    }

    /**
     * 获取模板与实参的对应关系
     *
     * @param parameterizedType
     * @return
     */
    protected Map<TypeVariable, Type> getTypeMap(ParameterizedType parameterizedType) {
        // 创建一个用于存储类型变量和对应的类型的映射 Map 对象
        Map<TypeVariable, Type> typeMap = new HashMap<>();
        // 获取实际类型参数数组和类型变量数组
        Type[] types = parameterizedType.getActualTypeArguments();
        TypeVariable[] typeParameters = ((Class) parameterizedType.getRawType()).getTypeParameters();
        // 遍历类型变量数组，并将对应的类型存入 Map 对象
        for (int i = 0; i < types.length; i++) {
            typeMap.put(typeParameters[i], types[i]);
        }
        // 返回存储类型变量和对应类型的映射 Map 对象
        return typeMap;

    }

    protected String converTypeName(Type type) {
        // 判断type是否是ParameterizedType类型
        if(type instanceof ParameterizedType){
            // 将type转换为ParameterizedType类型
            ParameterizedType parameterizedType = (ParameterizedType) type;
            // 获取rawType
            Class rawType = (Class) parameterizedType.getRawType();
            // 判断rawType是否是Collection类的子类
            if(Collection.class.isAssignableFrom(rawType)){
                // 获取参数类型数组
                Type[] params = parameterizedType.getActualTypeArguments();
                if(params.length>0){
                    // 转换params[0]的类型名称并返回数组类型名称
                    return converTypeName(params[0])+"[]";
                }else{
                    // 返回Object类的名称作为数组类型名称
                    return Object.class.getName()+"[]";
                }
            }else{
                // 返回rawType的类型名称
                return rawType.getName();
            }
        }else{
            // 返回type的类型名称
            return type.getTypeName();
        }

    }

    /**
     * 判断是否为数组
     * @param type
     * @return
     */
    protected boolean isArrayType(Type type){
         if (type instanceof ParameterizedType) {
            // 如果类型是ParameterizedType的实例
            Type rawType = ((ParameterizedType) type).getRawType();
            // 获取原始类型
            if (Collection.class.isAssignableFrom((Class) rawType)) {
                // 如果原始类型是Collection的子类
                return true;
                // 返回true
            }
        } else if(type instanceof Class){
            // 如果类型是Class的实例
            return ((Class)type).isArray()||Collection.class.isAssignableFrom((Class)type);
            // 返回类型是否为数组或者Collection的子类
        }
        return false;
        // 返回false

    }
}
